from tortoise.expressions import Q
from app.controllers.appointment.instrument import appointment_instrument_controller
from app.controllers.appointment.project import appointment_project_controller
from app.core.redis_base import redis_get, redis_set
from app.controllers.appointment.space import appointment_space_controller
from app.core.crud import CRUDBase
from app.controllers.appointment.designer import appointment_designer_controller
from app.core.ctx import CTX_USER_ID
from app.models import SchedulingDates, AppointmentLock, AppointmentList
from app.models.appointment import AppointmentInstrument
from datetime import datetime, timedelta


class AppointmentMiniController:
    def __init__(self):
        self.user_id = CTX_USER_ID.get()

    @staticmethod
    async def create_30days():
        # 生成包含今天在内的30天的日期列表
        dates = [datetime.now() + timedelta(days=i) for i in range(5)]
        weekdays = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"]
        dates_all = []
        # 输出日期列表
        for date in dates:
            weekday_index = date.weekday()
            weekday_name = weekdays[weekday_index]
            one_item = {
                "name": weekday_name,
                "time": date.strftime('%m.%d')
            }
            dates_all.append(one_item)
        return dates_all

    @staticmethod
    def convert_to_yyyy_mm_dd(date_str, year=None):
        # 分割字符串，获取月份和日期
        month, day = date_str.split('.')

        # 如果未指定年份，则使用当前年份
        if year is None:
            year = datetime.now().year

        # 构建完整的日期字符串
        full_date_str = f"{year}-{month}-{day}"

        # 验证日期是否有效（可选）
        try:
            datetime.strptime(full_date_str, '%Y-%m-%d')
        except ValueError:
            raise ValueError("输入的日期无效")

        return full_date_str

    @staticmethod
    def generate_time_slots(start, end, interval):
        # 将开始时间和结束时间转换为 datetime 对象
        start_time = datetime.strptime(start, '%H:%M')
        end_time = datetime.strptime(end, '%H:%M')

        # 初始化时间列表
        time_slots = []

        # 循环生成时间点
        current_time = start_time
        while current_time < end_time:
            # 将时间点添加到列表
            time_slots.append(current_time.strftime('%H:%M'))
            # 增加时间间隔
            current_time += timedelta(minutes=interval)

        return time_slots

    @staticmethod
    def remove_cancel_times(times_all, cancel_time, longs):
        # 1. 如果 cancel_time 是字符串，将其转换为 datetime 对象
        if isinstance(cancel_time, str):
            cancel_time_obj = datetime.strptime(cancel_time, "%Y-%m-%d %H:%M:%S.%f")
        else:
            cancel_time_obj = cancel_time
        # 2. 计算剔除范围的结束时间
        cancel_end_time_obj = cancel_time_obj + timedelta(minutes=longs)
        # 3. 将 times_all 中的时间转换为时间对象
        times_all_objs = [datetime.strptime(time, "%H:%M") for time in times_all]
        # 4. 筛选出不在剔除范围内的时间点
        filtered_times = [
            time for time in times_all_objs
            if not (cancel_time_obj.time() <= time.time() < cancel_end_time_obj.time())
        ]
        # 5. 将时间对象转换回字符串格式
        filtered_times_str = [time.strftime("%H:%M") for time in filtered_times]
        return filtered_times_str

    ##目前直接返回所有的日期
    async def get_date(self, request, space_id, type_id, doctor_id, project_id):
        dates_all = await self.create_30days()
        return dates_all

    async def get_times1(self, request, space_id, type_id, doctor_ids, project_id, date):
        print("开始")
        times_all = []
        times_can = []
        times_dis = []
        open_roles = []
        close_roles = []
        designer_interval = 0
        instrument_interval = 0
        num = 1  ##同一时间可以约的人数

        ##1.计算门店的开门时间,关门时间
        space = await appointment_space_controller.do_detail(space_id)
        start = space['start']
        end = space['end']
        interval = space_interval = space['interval']

        times_all = self.generate_time_slots(start=start, end=end, interval=interval)

        # 医生
        if doctor_ids:
            for doctor_id in doctor_ids:
                designer = await appointment_designer_controller.do_detail(doctor_id)
                open_roles = designer["open_roles"]  ##space_id,dates,interval,start,end
                close_roles = designer["close_roles"]
                if open_roles:
                    for open_role in open_roles:
                        designer_dates = open_role['dates']
                        if space_id == open_role['space_id'] and date in designer_dates:
                            ## 如果医生那边单独设置开始结束时间,按照这个优先
                            start = open_role['start']
                            end = open_role['end']
                            designer_interval = open_role['interval']
                            ## 开始生产时间段

        if designer_interval > 0:
            interval = designer_interval

        ##2.遍历时间
        start = f"{date} {start}"
        end = f"{date} {end}"
        time_format = "%Y-%m-%d %H:%M"
        time_format3 = "%Y-%m-%d %H:%M:%S"
        time_format2 = "%H:%M"
        start = datetime.strptime(start, time_format)
        end = datetime.strptime(end, time_format)
        temp_time = start

        while temp_time < end:
            new_time_string = temp_time.strftime(time_format2)
            times_all.append(new_time_string)
            if close_roles:
                for close_role in close_roles:
                    close_start = close_role['start']
                    close_end = close_role['end']
                    if close_start and close_end:
                        close_start = datetime.strptime(close_start, time_format3)
                        close_end = datetime.strptime(close_end, time_format3)
                        if close_start <= temp_time < close_end:
                            new_time_string = temp_time.strftime(time_format2)
                            times_dis.append(new_time_string)
            temp_time = temp_time + timedelta(minutes=interval)

        times_can = [value for value in times_all if value not in times_dis]

        ##还要排除已经约的时间段，注意每个时间段可约次数num
        return times_all, times_can

    async def get_times(self, request, space_id, type_id, doctor_ids, project_id, date):
        print("开始获取时间段")
        ##1.计算门店的开门时间,关门时间,只有门店可以设置预约时间间隔
        space = await appointment_space_controller.do_detail(space_id)
        space_start = space['start']
        space_end = space['end']
        interval = space['interval']
        if doctor_ids is None:
            print("无doctor_ids")
            times_all = self.generate_time_slots(start=space_start, end=space_end, interval=interval)
            return times_all
        print("interval", interval)
        print("space_id", space_id)
        print("doctor_ids", doctor_ids)
        print("date", date)
        ##2.获取多个技师的交叉时间
        data = await SchedulingDates.filter(space_id=space_id, date=date, designer_id__in=doctor_ids).values(
            "designer_id", "start", "end")
        start_max = space_start
        end_min = space_end
        for item in data:
            d_id = item["designer_id"]
            start = item["start"]  ##09:00
            end = item["end"]  ##17:00
            print(f"{d_id}排班时间:{start}至{end}")
            # 更新最大开始时间
            if start > start_max:
                start_max = start
            # 更新最小结束时间
            if end < end_min:
                end_min = end
            # 检查是否有有效交叉时间
        if start_max < end_min:
            print(f"交叉时间:{start_max}至{end_min}")
            times_all = self.generate_time_slots(start=start_max, end=end_min, interval=interval)

            # times_all = ["12:00","12:30","13:00","13:30","14:00"]
            q = Q(time__contains=date)
            # 将或逻辑部分用括号包起来
            or_condition = Q()
            for designer_id in doctor_ids:
                or_condition |= Q(designer_ids__contains=[int(designer_id)])

            combined_condition = q & or_condition

            lock_data = await AppointmentLock.filter(combined_condition).values("time", "longs")
            if lock_data:
                print(f"查询到lock表占位")
                for item in lock_data:
                    cancel_time = item["time"]  ##2025-02-25 12:30:00
                    longs = item["longs"]  ## 60分钟
                    times_all = self.remove_cancel_times(times_all, cancel_time, longs)

            appointment_data = await AppointmentList.filter(combined_condition).filter(status__in=[0, 1]).values("time",
                                                                                                                 "longs")
            if appointment_data:
                for item in appointment_data:
                    cancel_time = item["time"]  ##2025-02-25 12:30:00
                    longs = item["longs"]  ## 60分钟
                    print(f"查询到预约记录表占位{cancel_time}时长{longs}")
                    times_all = self.remove_cancel_times(times_all, cancel_time, longs)
        else:
            times_all = []
        return times_all


appointment_mini_controller = AppointmentMiniController()
